package com.changanw.middleware.mybatis.spring;


import com.changanw.middleware.mybatis.SqlSessionFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils;

import java.beans.Introspector;
import java.io.IOException;

/**
 *这个类要处理的核心内容，就是把 DAO 接口全部扫描出来，完成代理和注册到 Spring Bean 容器。
 *
 */
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor {

    private String basePackage;
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //加入判空操作，防止空指针
        if (basePackage != null){
            try {
                // classpath*:cn/bugstack/**/dao/**/*.class
                String packageSearchPath = "classpath*:" + basePackage.replace('.', '/') + "/**/*.class";
                //类的扫描注册，classpath:com/changanw/xx/dao/**/.class，解析calss文件获取资源信息；
                // Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
                ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
                Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);

                //遍历 Resource，这里就你的 class 信息，用于注册 bean。ScannedGenericBeanDefinition
                for (Resource resource : resources) {
                    MetadataReader metadataReader = new SimpleMetadataReader(resource, ClassUtils.getDefaultClassLoader());

                    ScannedGenericBeanDefinition beanDefinition = new ScannedGenericBeanDefinition(metadataReader);
                    String beanName = Introspector.decapitalize(ClassUtils.getShortName(beanDefinition.getBeanClassName()));

                    beanDefinition.setResource(resource);
                    beanDefinition.setSource(resource);
                    beanDefinition.setScope("singleton");
                    beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition.getBeanClassName());
                    //适配start的更改，注释掉此部分
                    //beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(sqlSessionFactory);
                    //这里有一点，bean的定义设置时候，
                    // 是把 beanDefinition.setBeanClass(MapperFactoryBean.class); 设置进去的。同时在前面给他设置了构造参数。
                    beanDefinition.setBeanClass(MapperFactoryBean.class);

                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
                    //最后执行注册 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
                    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // left intentionally blank
    }

    public void setBasePackage(String basePackage) {
        this.basePackage = basePackage;
    }

    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
}
